#include <iostream>
using namespace std;
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

enum
{
    SOCK_ERROR = 1,
    BIND_ERROR,
    USAGE_ERROR,
    RECV_ERROR
};

const static int defaultsockfd = -1;
const static int gbacklog = 8;

class TcpServer; // 先声明，再使用 !!!

class ServerData
{
public:
    ServerData(TcpServer* tsvr_ptr, int sockfd) 
    :_tsvr_ptr(tsvr_ptr), _peerfd(sockfd)
    {}

    TcpServer* Self()
    {
        return _tsvr_ptr;
    }

    int Sockfd()
    {
        return _peerfd;
    }

    ~ServerData()
    {}
private:
    TcpServer* _tsvr_ptr;
    int _peerfd;
};

class TcpServer
{
public:
    TcpServer(uint16_t port) : _listenfd(defaultsockfd), _port(port), _isrunning(false)
    {
    }

    void InitServer()
    {
        // 1. 创建套接字
        // int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        // if (sockfd < 0)
        // {
        //     cout << __LINE__ << " : socket error" << endl;
        //     exit(SOCK_ERROR);
        // }
        _listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listenfd < 0)
        {
            cout << __LINE__ << " : socket error" << endl;
            exit(SOCK_ERROR);
        }
        cout << __LINE__ << " : socket success, sockfd: " << _listenfd << endl;

        // 2. bind
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;

        int n = bind(_listenfd, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            cout << __LINE__ << " : bind error" << endl;
            exit(BIND_ERROR);
        }
        cout << __LINE__ << " : bind success" << endl;

        // 3. listen
        n = listen(_listenfd, gbacklog);
        if (n < 0)
        {
            cout << __LINE__ << " : listen error" << endl;
        }
        cout << __LINE__ << " : listen success" << endl;
    }

    void Server(int sockfd)
    {
        // pthread_detach(pthread_self());
        while (1)
        {
            // 2. recv
            char buffer[1024];
            ssize_t m = recv(sockfd, buffer, 1024, 0);
            if (m > 0)
            {
                buffer[m] = 0;
                cout << __LINE__ << " : get message# " << buffer << endl;

                // 3. send
                m = send(sockfd, buffer, strlen(buffer), 0);
                if (m < 0)
                {
                    cout << __LINE__ << " : echo message error" << endl;
                }
                
            }
            else if (m == 0)
            {
                break;
            }
            else // m < 0
            {
                cout << __LINE__ << " : recv error" << endl;
                exit(RECV_ERROR);
            }
        }
        // pthread_join(pthread_self(), nullptr);
    }

    static void* HandlerServer(void* arg)
    {
        ServerData* ptr = static_cast<ServerData*>(arg);
        ptr->Self()->Server(ptr->Sockfd());
        return nullptr;
    }

    void Start()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // 1. accept
            struct sockaddr_in peer;
            bzero(&peer, sizeof(peer));
            socklen_t len = sizeof(peer);
            int peerfd = accept(_listenfd, (struct sockaddr *)&peer, &len);
            if (peerfd < 0)
            {
                cout << __LINE__ << " : accept error" << endl;
                continue;
            }

            // Version 1 多进程版本 -- 未写完整 -- 没有关闭父子进程对应的文件描述符
            pid_t id = fork();
            if (id == 0)
            {
                close(_listenfd); // 可要可不要
                pid_t id2 = fork();
                if (id2 > 0) 
                {
                    exit(0);
                }
                Server(peerfd);
            }
            // 父进程关闭 peerfd -- 必须要 !!
            close(peerfd);
            waitpid(id, nullptr, 0);

            // Version 2 多线程版本
            // ServerData* data = new ServerData(this, peerfd);
            // // func_t func = bind(&Server, this, peerfd, nullptr);
            // pthread_t thread;
            // int n = pthread_create(&thread, nullptr, HandlerServer, data);
            // if (n < 0)
            // {
            //     cout << __LINE__ << " : server error" << endl;
            // }
            // // pthread_join(thread, nullptr);
        }
        _isrunning = false;
    }

    // void Start() // 乱写 !!!
    // {
    //     _isrunning = true;
    //     while (_isrunning)
    //     {
    //         // 1. 读数据
    //         char buffer[1024];
    //         ssize_t n = recv(_sockfd, buffer, 1024, 0);
    //         if (n > 0)
    //         {
    //             buffer[n] = 0;
    //             cout << __LINE__ << " : recv success" << endl;
    //             // 2. 发数据

    //             n = send(_sockfd, buffer, strlen(buffer), 0);
    //             if (n < 0)
    //             {
    //                 cout << __LINE__ << " : send error" << endl;
    //                 continue;
    //             }
    //             cout << __LINE__ << " : send success" << endl;
    //         }
    //     }
    //     _isrunning = false;
    // }

    ~TcpServer()
    {
    }

private:
    int _listenfd;
    uint16_t _port;
    bool _isrunning;
};